package com.my.study.design.ruleParallel;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: yidujun
 * @create: 2021/07/09 17:49
 */
public class RuleService {
    private Map<Integer, List<BaseRule>> map = new ConcurrentHashMap<>();
    private static final int OR = 0;
    private static final int AND = 1;

    //=======================使用静态内部类实现懒加载获取单例对象-start

    /**
     * 不允许外部显示创建RuleService对象
     */
//    private RuleService() {
//    }
//
//    private static class RuleServiceHolder {
//        static final RuleService INSTANCE = new RuleService();
//    }
//
//    public static RuleService getInstance() {
//        return RuleServiceHolder.INSTANCE;
//    }
    //=======================使用静态内部类实现懒加载获取单例对象-end

    public static RuleService create() {
        return new RuleService();
    }

    public RuleService and(BaseRule rule) {
        map.computeIfAbsent(AND, v -> getValue()).add(rule);
        return this;
    }

    public RuleService and(List<BaseRule> ruleList) {
        map.computeIfAbsent(AND, v -> getValue()).addAll(ruleList);
        return this;
    }

    public RuleService or(BaseRule rule) {
        map.computeIfAbsent(OR, v -> getValue()).add(rule);
        return this;
    }

    public RuleService or(List<BaseRule> ruleList) {
        map.computeIfAbsent(OR, v -> getValue()).addAll(ruleList);
        return this;
    }

    public boolean execute(Object obj) {
        for (Map.Entry<Integer, List<BaseRule>> item : map.entrySet()) {
            List<BaseRule> rules = item.getValue();
            switch (item.getKey()) {
                case AND:
                    // 如果是 and 关系，同步执行
                    if (!and(obj, rules)) {
                        return false;
                    }
                    break;
                case OR:
                    // 如果是 or 关系，并行执行
                    if (!or(obj, rules)) {
                        return false;
                    }
                    break;
                default:
                    break;
            }
        }
        return true;
    }

    private boolean and(Object obj, List<BaseRule> rules) {
        for (BaseRule rule : rules) {
            boolean execute = rule.execute(obj);
            if (!execute) {
                // and 关系匹配失败一次，返回 false
                return false;
            }
        }
        // and 关系全部匹配成功，返回 true
        return true;
    }

    private boolean or(Object obj, List<BaseRule> rules) {
        for (BaseRule rule : rules) {
            boolean execute = rule.execute(obj);
            if (execute) {
                // or 关系匹配到一个就返回 true
                return true;
            }
        }
        // or 关系一个都匹配不到就返回 false
        return false;
    }

    private static List<BaseRule> getValue() {
        return new ArrayList<>();
    }
}
